<?php


namespace App\Commons\Utils\ModelTools;

use Carbon\Carbon;

trait FilterQueryTrait
{
    private $_dataFormat='Y-m-d H:i:s';
    /**
     * @param        $query
     * @param int    $type
     * @param string $fieldName
     * @param string $fieldType 1 等于 2 不等于 3 包含 4 不包含 5 起始字符 6 大于 7 大于等于 8 小于 9 小于等于 10 今天(value值为空) 11 昨天(value值为空) 12
     *                          本月(value值为空) 13 上月(value值为空) 14 今年(value值为空) 15 去年(value值为空) 16 过去多少天内 17 过去多少天前 18
     *                          在未来多少天内 19 在未来多少天前 20 在指定多少天后  22为空  24 不为空 25
     *                          区间查询(值类型为以逗号隔开的两个时间戳拼成的字符串)
     * @param $value
     * @param $isRaw
     * @param $isApposition
     * @return mixed
     */
    public function  buildFilterQuery($query, int $type, string $fieldName, string $fieldType, $value, $isRaw = false, $isApposition = false)
    {
        if($isRaw){
            return ($operator = FilterQueryTypeEnum::operatorMap($type)) && $query->whereRaw($fieldName . $operator . '?',[$value]);
        }
        if($isApposition){
            foreach ($value as $v){
                $query->where($fieldName, 'like', "%,$v,%");
            }
            return;
        }
        switch ($type) {
            default:
            case FilterQueryTypeEnum::EQUAL:
                //字段类型为select时 不改变值的类型
                $value = $fieldType == 'select' ? $value : $this->_transFormatByFieldType($fieldType, $value);
                $query->where($fieldName, $value);
                break;
            case FilterQueryTypeEnum::NOT_EQUAL:
                $query->where($fieldName, '!=', $this->_transFormatByFieldType($fieldType, $value));
                break;
            case FilterQueryTypeEnum::CONTAIN:
                $query->where($fieldName, 'like', "%$value%");
                break;
            case FilterQueryTypeEnum::NOT_CONTAIN:
                $query->where($fieldName, 'not like', "%$value%");
                break;
            case FilterQueryTypeEnum::START_SIGN:
                $query->where($fieldName, 'like', "$value%");
                break;
            case FilterQueryTypeEnum::MORE_THAN:
                $query->where($fieldName, '>', $this->_transFormatByFieldType($fieldType, $value));
                break;
            case FilterQueryTypeEnum::MORE_THAN_AND_EQUAL:
                $query->where($fieldName, '>=', $this->_transFormatByFieldType($fieldType, $value));
                break;
            case FilterQueryTypeEnum::LESS_THAN:
                $query->where($fieldName, '<', $this->_transFormatByFieldType($fieldType, $value));
                break;
            case FilterQueryTypeEnum::LESS_THAN_AND_EQUAL:
                $query->where($fieldName, '<=', $this->_transFormatByFieldType($fieldType, $value));
                break;
            case FilterQueryTypeEnum::TODAY:
                $query->where($fieldName, '>', Carbon::now()->startOfDay());
                $query->where($fieldName, '<', Carbon::now()->endOfDay());
                break;
            case FilterQueryTypeEnum::YESTERDAY:
                $query->where($fieldName, '>', Carbon::now()->addDay(-1)->startOfDay());
                $query->where($fieldName, '<', Carbon::now()->addDay(-1)->endOfDay());
                break;
            case FilterQueryTypeEnum::THIS_MONTH:
                $query->where($fieldName, '>', Carbon::now()->startOfMonth());
                $query->where($fieldName, '<=', Carbon::now()->endOfMonth());
                break;
            case FilterQueryTypeEnum::LAST_MONTH:
                $query->where($fieldName, '>', Carbon::now()->addMonth(-1)->startOfMonth());
                $query->where($fieldName, '<', Carbon::now()->addMonth(-1)->endOfMonth());
                break;
            case FilterQueryTypeEnum::THIS_YEAR:
                $query->where($fieldName, '>', Carbon::now()->startOfYear());
                $query->where($fieldName, '<', Carbon::now()->endOfYear());
                break;
            case FilterQueryTypeEnum::LAST_YEAR:
                $query->where($fieldName, '>', Carbon::now()->addYear(-1)->startOfYear());
                $query->where($fieldName, '<', Carbon::now()->addYear(-1)->endOfYear());
                break;
            case FilterQueryTypeEnum::PAST_DAYS:
                $query->where($fieldName, '>', Carbon::now()->addDay(-$value)->startOfDay());
                $query->where($fieldName, '<', Carbon::now()->startOfDay());
                break;
            case FilterQueryTypeEnum::PAST_DAY_BEFORE:
                $query->where($fieldName, '<', Carbon::now()->addDay(-$value)->startOfDay());
                break;
            case FilterQueryTypeEnum::IN_DAYS:
                $query->where($fieldName, '>', Carbon::now()->endOfDay());
                $query->where($fieldName, '<', Carbon::now()->addDay((int)$value)->endOfDay());
                break;
            case FilterQueryTypeEnum::IN_DAYS_BEFORE:
                $query->where($fieldName, '<', Carbon::now()->addDay((int)$value)->endOfDay());
                break;
            case FilterQueryTypeEnum::IN_DAYS_LATER:
                $query->where($fieldName, '>', Carbon::now()->addDay((int)$value)->startOfDay());
                break;
            case FilterQueryTypeEnum::IS_EMPTY:
                $query->where($fieldName, '');
                break;
            case FilterQueryTypeEnum::NOT_EMPTY:
                $query->where($fieldName, '!=', '');
                break;
            case FilterQueryTypeEnum::IN:
                $query->whereIn($fieldName, is_array($value) ? $value : explode(',', $value));
                break;
        }
    }


    /**
     * @param string $fieldType
     * @param string $value
     *
     * @return float|string
     */
    private function _transFormatByFieldType(string $fieldType, string $value)
    {
        switch ($fieldType) {
            default:
            case 'text':
                return (string)$value;
            case 'number':
                return floatval($value);
            case 'datetime':
                return Carbon::createFromTimestamp($value / 1000);
            case 'daterange':
                return (float)$value;
        }
    }


}